package com.qk.util;

import cn.hutool.core.text.StrBuilder;
import cn.hutool.core.util.StrUtil;
import com.alibaba.cloudapi.sdk.client.ApacheHttpClient;
import com.alibaba.cloudapi.sdk.constant.SdkConstant;
import com.alibaba.cloudapi.sdk.enums.HttpMethod;
import com.alibaba.cloudapi.sdk.enums.ParamPosition;
import com.alibaba.cloudapi.sdk.enums.Scheme;
import com.alibaba.cloudapi.sdk.model.ApiCallback;
import com.alibaba.cloudapi.sdk.model.ApiRequest;
import com.alibaba.cloudapi.sdk.model.ApiResponse;
import com.alibaba.cloudapi.sdk.model.HttpClientBuilderParams;
import com.qk.util.property.HttpsApiClientWeatherProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;

/**
 * @Author: zhangchuang
 * @Date: 2025/10/09 16:22
 * @Description: 获取天气api类
 */
@Component
@SuppressWarnings("all")
public class HttpsApiClientWeather extends ApacheHttpClient {

    @Autowired
    private HttpsApiClientWeatherProperties httpsApiClientWeatherProperties;

    private final static String HOST = "ali-weather.showapi.com";
    public final static String HTTP = "HTTP";
    public final static String HTTPS = "HTTPS";
    private final static String PATH_DAY15 = "/day15";
    private final static String PATH_HOUR24 = "/day15";
    private final static String PATH_DAY40 = "/day40";
    private final static String PATH_ONE_IN_DAY7 = "/area-to-weather-date";
    private final static String PATH_IP = "/ip-to-weather";
    private final static String PATH_AREA = "/area-to-weather";
    private final static String PATH_POST_CODE = "/phone-post-code-weeather";
    private final static String PATH_AREA_NAME = "/area-to-id";
    private final static String PATH_HISTORY = "/weatherhistory";
    private final static String PATH_SCENIC_SPOT = "/spot-to-weather";
    private final static String PATH_GPS = "/gps-to-weather";

    private final static String PARAM_AREAID = "areaid";
    private final static String PARAM_AREA = "area";
    private final static String PARAM_AREACODE = "areaCode";
    private final static String PARAM_DATE = "date";
    private final static String PARAM_NEED3HOURFORCAST = "need3HourForcast";
    private final static String PARAM_IP = "ip";
    private final static String PARAM_NEEDMOREDAY = "needMoreDay";
    private final static String PARAM_NEEDINDEX = "needIndex";
    private final static String PARAM_NEEDHOURDATA = "needHourData";
    private final static String PARAM_NEED3HOURFORECAST = "need3HourForcast";
    private final static String PARAM_NEEDALARM = "needAlarm";
    private final static String PARAM_POST_CODE = "post_code";
    private final static String PARAM_PHONE_CODE = "phone_code";
    private final static String PARAM_MONTH = "month";
    private final static String PARAM_START_DATE = "startDate";
    private final static String PARAM_ENDDATE = "endDate";
    private final static String PARAM_FROM = "from";
    private final static String PARAM_LNG = "lng";
    private final static String PARAM_LAT = "lat";

    public void init(String policy) {
        HttpClientBuilderParams httpsParam = new HttpClientBuilderParams();
        httpsParam.setAppKey(httpsApiClientWeatherProperties.getAppKey());
        httpsParam.setAppSecret(httpsApiClientWeatherProperties.getAppSecret());
        httpsParam.setHost(HOST);
        if (StrUtil.equals(HTTP, policy)) {
            //HTTP Client init
            httpsParam.setScheme(Scheme.HTTP);
        } else {
            //HTTPS Client init
            httpsParam.setScheme(Scheme.HTTPS);
        }
        super.init(httpsParam);
    }

    public String getResultString(ApiResponse response) throws IOException {
        StrBuilder result = StrBuilder.create()
                .append("Response from backend server").append(SdkConstant.CLOUDAPI_LF)
                .append(SdkConstant.CLOUDAPI_LF).append("ResultCode:")
                .append(SdkConstant.CLOUDAPI_LF).append(response.getCode())
                .append(SdkConstant.CLOUDAPI_LF).append(SdkConstant.CLOUDAPI_LF);
        if (response.getCode() != 200) {
            result.append("Error description:").append(response.getHeaders().get("X-Ca-Error-Message"))
                    .append(SdkConstant.CLOUDAPI_LF).append(SdkConstant.CLOUDAPI_LF);
        }
        result.append("ResultBody:").append(SdkConstant.CLOUDAPI_LF)
                .append(new String(response.getBody(), SdkConstant.CLOUDAPI_ENCODING));

        return result.toString();
    }

    private ApiRequest requestIntervalBuild(String path, String areaId, String area, String areaCode) {
        ApiRequest request = new ApiRequest(HttpMethod.GET, path);
        request.addParam(PARAM_AREAID, areaId, ParamPosition.QUERY, false);
        request.addParam(PARAM_AREA, area, ParamPosition.QUERY, false);
        request.addParam(PARAM_AREACODE, areaCode, ParamPosition.QUERY, false);

        return request;
    }

    private ApiRequest requestPointBuild(String areaCode, String areaId, String area,
                                         String date, String need3HourForecast) {
        ApiRequest request = new ApiRequest(HttpMethod.GET, PATH_ONE_IN_DAY7);
        request.addParam(PARAM_AREAID, areaId, ParamPosition.QUERY, false);
        request.addParam(PARAM_AREA, area, ParamPosition.QUERY, false);
        request.addParam(PARAM_DATE, date, ParamPosition.QUERY, false);
        request.addParam(PARAM_NEED3HOURFORCAST, need3HourForecast, ParamPosition.QUERY, false);

        return request;
    }

    private ApiRequest requestIPBuild(String ip, String needMoreDay, String needIndex,
                                      String needHourData, String need3HourForecast, String needAlarm) {
        ApiRequest request = new ApiRequest(HttpMethod.GET, PATH_IP);
        request.addParam(PARAM_IP, ip, ParamPosition.QUERY, true);
        request.addParam(PARAM_NEEDMOREDAY, needMoreDay, ParamPosition.QUERY, false);
        request.addParam(PARAM_NEEDINDEX, needIndex, ParamPosition.QUERY, false);
        request.addParam(PARAM_NEEDHOURDATA, needHourData, ParamPosition.QUERY, false);
        request.addParam(PARAM_NEED3HOURFORECAST, need3HourForecast, ParamPosition.QUERY, false);
        request.addParam(PARAM_NEEDALARM, needAlarm, ParamPosition.QUERY, false);

        return request;
    }

    private ApiRequest requestAreaBuild(String areaid, String area, String areaCode, String needMoreDay, String needIndex,
                                        String need3HourForecast, String needAlarm, String needHourData) {
        ApiRequest request = new ApiRequest(HttpMethod.GET, PATH_AREA);
        request.addParam(PARAM_AREAID, areaid, ParamPosition.QUERY, false);
        request.addParam(PARAM_AREA, area, ParamPosition.QUERY, false);
        request.addParam(PARAM_AREACODE, areaCode, ParamPosition.QUERY, false);
        request.addParam(PARAM_NEEDMOREDAY, needMoreDay, ParamPosition.QUERY, false);
        request.addParam(PARAM_NEEDINDEX, needIndex, ParamPosition.QUERY, false);
        request.addParam(PARAM_NEED3HOURFORECAST, need3HourForecast, ParamPosition.QUERY, false);
        request.addParam(PARAM_NEEDALARM, needAlarm, ParamPosition.QUERY, false);
        request.addParam(PARAM_NEEDHOURDATA, needHourData, ParamPosition.QUERY, false);

        return request;
    }

    private ApiRequest requestPostCodeBuild(String post_code, String phone_code, String needMoreDay, String needIndex,
                                            String needHourData, String need3HourForecast, String needAlarm) {
        ApiRequest request = new ApiRequest(HttpMethod.GET, PATH_POST_CODE);
        request.addParam(PARAM_POST_CODE, post_code, ParamPosition.QUERY, false);
        request.addParam(PARAM_PHONE_CODE, phone_code, ParamPosition.QUERY, false);
        request.addParam(PARAM_NEEDMOREDAY, needMoreDay, ParamPosition.QUERY, false);
        request.addParam(PARAM_NEEDINDEX, needIndex, ParamPosition.QUERY, false);
        request.addParam(PARAM_NEED3HOURFORECAST, need3HourForecast, ParamPosition.QUERY, false);
        request.addParam(PARAM_NEEDALARM, needAlarm, ParamPosition.QUERY, false);
        request.addParam(PARAM_NEEDHOURDATA, needHourData, ParamPosition.QUERY, false);

        return request;
    }

    private ApiRequest requestAreaNameBuild(String area) {
        ApiRequest request = new ApiRequest(HttpMethod.GET, PATH_AREA_NAME);
        request.addParam(PARAM_AREA, area, ParamPosition.QUERY, true);

        return request;
    }

    private ApiRequest requestHistoryBuild(String areaid, String areaCode, String area,
                                           String month, String startDate, String endDate) {
        ApiRequest request = new ApiRequest(HttpMethod.GET, PATH_HISTORY);
        request.addParam(PARAM_AREAID, areaid, ParamPosition.QUERY, false);
        request.addParam(PARAM_AREAID, areaCode, ParamPosition.QUERY, false);
        request.addParam(PARAM_AREA, area, ParamPosition.QUERY, false);
        request.addParam(PARAM_MONTH, month, ParamPosition.QUERY, false);
        request.addParam(PARAM_START_DATE, startDate, ParamPosition.QUERY, false);
        request.addParam(PARAM_ENDDATE, endDate, ParamPosition.QUERY, false);

        return request;
    }

    private ApiRequest requestScenicSpotBuild(String area, String needMoreDay, String needIndex,
                                              String needHourData, String need3HourForcast, String needAlarm) {
        ApiRequest request = new ApiRequest(HttpMethod.GET, PATH_SCENIC_SPOT);
        request.addParam(PARAM_AREA, area, ParamPosition.QUERY, true);
        request.addParam(PARAM_NEEDMOREDAY, needMoreDay, ParamPosition.QUERY, false);
        request.addParam(PARAM_NEEDINDEX, needIndex, ParamPosition.QUERY, false);
        request.addParam(PARAM_NEEDHOURDATA, needHourData, ParamPosition.QUERY, false);
        request.addParam(PARAM_NEED3HOURFORECAST, need3HourForcast, ParamPosition.QUERY, false);
        request.addParam(PARAM_NEEDALARM, needAlarm, ParamPosition.QUERY, false);

        return request;
    }

    private ApiRequest requestGPSBuild(String from, String lng, String lat, String needMoreDay, String needIndex,
                                       String needHourData, String need3HourForecast, String needAlarm) {
        ApiRequest request = new ApiRequest(HttpMethod.GET, PATH_GPS);
        request.addParam(PARAM_FROM, from, ParamPosition.QUERY, false);
        request.addParam(PARAM_LNG, lng, ParamPosition.QUERY, true);
        request.addParam(PARAM_LAT, lat, ParamPosition.QUERY, true);
        request.addParam(PARAM_NEEDMOREDAY, needMoreDay, ParamPosition.QUERY, false);
        request.addParam(PARAM_NEEDINDEX, needIndex, ParamPosition.QUERY, false);
        request.addParam(PARAM_NEEDHOURDATA, needHourData, ParamPosition.QUERY, false);
        request.addParam(PARAM_NEED3HOURFORECAST, need3HourForecast, ParamPosition.QUERY, false);
        request.addParam(PARAM_NEEDALARM, needAlarm, ParamPosition.QUERY, false);

        return request;
    }

    /**
     * 异步未来15天预报
     *
     * @param areaId   地区id. 此参数和area、areaCode必须输入一个。
     * @param area     地区名称
     * @param areaCode 地区code. 此参数和area必须输入一个。
     * @param callback 回调函数
     */
    public void forecast15Days(String areaId, String area, String areaCode, ApiCallback callback) {
        ApiRequest request = requestIntervalBuild(PATH_DAY15, areaId, area, areaCode);

        sendAsyncRequest(request, callback);
    }

    /**
     * 未来15天预报
     *
     * @param areaId   地区id. 此参数和area、areaCode必须输入一个。
     * @param area     地区名称
     * @param areaCode 地区code. 此参数和area必须输入一个。
     * @return ApiResponse
     */
    public ApiResponse forecast15DaysSyncMode(String areaId, String area, String areaCode) {
        ApiRequest request = requestIntervalBuild(PATH_DAY15, areaId, area, areaCode);

        return sendSyncRequest(request);
    }

    /**
     * 异步查询24小时预报
     *
     * @param areaId   地区id. 此参数和area、areaCode必须输入一个。
     * @param area     地区名称
     * @param areaCode 地区code. 此参数和area必须输入一个。
     * @param callback 回调函数
     */
    public void forecast24Hours(String areaId, String area, String areaCode, ApiCallback callback) {
        ApiRequest request = requestIntervalBuild(PATH_HOUR24, areaId, area, areaCode);

        sendAsyncRequest(request, callback);
    }

    /**
     * 查询24小时预报
     *
     * @param areaId   地区id. 此参数和area、areaCode必须输入一个。
     * @param area     地区名称
     * @param areaCode 地区code. 此参数和area必须输入一个。
     * @return ApiResponse
     */
    public ApiResponse forecast24HoursSyncMode(String areaId, String area, String areaCode) {
        ApiRequest request = requestIntervalBuild(PATH_HOUR24, areaId, area, areaCode);

        return sendSyncRequest(request);
    }

    /**
     * 异步查未来40天预报
     *
     * @param areaCode 地区code. 此参数和area必须输入一个。
     * @param areaId   地区id
     * @param area     地区名称
     * @param callback 回调函数
     */
    public void forecast40Days(String areaCode, String areaId, String area, ApiCallback callback) {
        ApiRequest request = requestIntervalBuild(PATH_DAY40, areaId, area, areaCode);

        sendAsyncRequest(request, callback);
    }

    /**
     * 查未来40天预报
     *
     * @param areaCode 地区code. 此参数和area必须输入一个。
     * @param areaId   地区id
     * @param area     地区名称
     * @return ApiResponse
     */
    public ApiResponse forecast40DaysSyncMode(String areaCode, String areaId, String area) {
        ApiRequest request = requestIntervalBuild(PATH_DAY40, areaId, area, areaCode);

        return sendSyncRequest(request);
    }

    /**
     * 异步未来7日中某天的天气预报
     *
     * @param areaCode          要查询的地区code
     * @param areaId            要查询的地区id（以后可能会废弃，以areaCode为准）
     * @param area              要查询的地区名称。areaCode与area字段必须输入其中一个。当两者都输入时，系统只取areaCode
     * @param date              查询日期
     * @param need3HourForecast 是否需要当天每3/6/8小时一次的天气预报列表。1为需要，0为不需要。注意f1是3小时间隔，但f2到f7的间隔可能是6或8小时。
     * @param callback          回调函数
     */
    public void forecastOneIn7Days(String areaCode, String areaId, String area, String date,
                                   String need3HourForecast, ApiCallback callback) {
        ApiRequest request = requestPointBuild(areaCode, areaId, area, date, need3HourForecast);

        sendAsyncRequest(request, callback);
    }

    /**
     * 未来7日中某天的天气预报
     *
     * @param areaCode          要查询的地区code
     * @param areaId            要查询的地区id（以后可能会废弃，以areaCode为准）
     * @param area              要查询的地区名称。areaCode与area字段必须输入其中一个。当两者都输入时，系统只取areaCode
     * @param date              查询日期
     * @param need3HourForecast 是否需要当天每3/6/8小时一次的天气预报列表。1为需要，0为不需要。注意f1是3小时间隔，但f2到f7的间隔可能是6或8小时。
     * @return ApiResponse
     */
    public ApiResponse forecastOneIn7DaysSyncMode(String areaCode, String areaId, String area,
                                                  String date, String need3HourForecast) {
        ApiRequest request = requestPointBuild(areaCode, areaId, area, date, need3HourForecast);

        return sendSyncRequest(request);
    }

    /**
     * IP异步查询天气预报
     *
     * @param ip                用户ip。必须
     * @param needMoreDay       是否需要返回7天数据中的后4天。1为返回，0为不返回。
     * @param needIndex         是否需要返回指数数据，比如穿衣指数、紫外线指数等。1为返回，0为不返回。
     * @param needHourData      是否需要每小时数据的累积数组。由于本系统是半小时刷一次实时状态，因此实时数组最大长度为48。每天0点长度初始化为0.
     * @param need3HourForecast 是否需要每小时数据的累积数组。由于本系统是半小时刷一次实时状态，因此实时数组最大长度为48。每天0点长度初始化为0.
     * @param needAlarm         是否需要天气预警。1为需要，0为不需要。
     * @param callback          回调函数
     */
    public void forecastByIP(String ip, String needMoreDay, String needIndex, String needHourData,
                             String need3HourForecast, String needAlarm, ApiCallback callback) {
        ApiRequest request = requestIPBuild(ip, needMoreDay, needIndex, needHourData, need3HourForecast, needAlarm);

        sendAsyncRequest(request, callback);
    }

    /**
     * IP查询天气预报
     *
     * @param ip                用户ip。必须
     * @param needMoreDay       是否需要返回7天数据中的后4天。1为返回，0为不返回。
     * @param needIndex         是否需要返回指数数据，比如穿衣指数、紫外线指数等。1为返回，0为不返回。
     * @param needHourData      是否需要每小时数据的累积数组。由于本系统是半小时刷一次实时状态，因此实时数组最大长度为48。每天0点长度初始化为0.
     * @param need3HourForecast 是否需要每小时数据的累积数组。由于本系统是半小时刷一次实时状态，因此实时数组最大长度为48。每天0点长度初始化为0.
     * @param needAlarm         是否需要天气预警。1为需要，0为不需要。
     * @return ApiResponse
     */
    public ApiResponse forecastByIPSyncMode(String ip, String needMoreDay, String needIndex,
                                            String needHourData, String need3HourForecast, String needAlarm) {
        ApiRequest request = requestIPBuild(ip, needMoreDay, needIndex, needHourData, need3HourForecast, needAlarm);

        return sendSyncRequest(request);
    }

    /**
     * 地名异步查询天气预报
     *
     * @param areaId            地区id
     * @param area              地区名称。名称和code必须输入一个。如果都输入，以areaCode为准。
     * @param areaCode          地区code。名称和code必须输入一个。如果都输入，以areaCode为准。
     * @param needMoreDay       是否需要返回7天数据中的后4天。1为返回，0为不返回。
     * @param needIndex         是否需要返回指数数据，比如穿衣指数、紫外线指数等。1为返回，0为不返回。
     * @param need3HourForecast 是否需要每小时数据的累积数组。由于本系统是半小时刷一次实时状态，因此实时数组最大长度为48。每天0点长度初始化为0. 1为需要 0为不
     * @param needAlarm         是否需要天气预警。1为需要，0为不需要。
     * @param needHourData      是否需要每小时数据的累积数组。由于本系统是半小时刷一次实时状态，因此实时数组最大长度为48。每天0点长度初始化为0.
     * @param callback          回调函数
     */
    public void forecastByArea(String areaId, String area, String areaCode, String needMoreDay, String needIndex,
                               String need3HourForecast, String needAlarm, String needHourData, ApiCallback callback) {
        ApiRequest request = requestAreaBuild(areaId, area, areaCode, needMoreDay, needIndex, need3HourForecast, needAlarm, needHourData);

        sendAsyncRequest(request, callback);
    }

    /**
     * 地名查询天气预报
     *
     * @param areaId            地区id
     * @param area              地区名称。名称和code必须输入一个。如果都输入，以areaCode为准。
     * @param areaCode          地区code。名称和code必须输入一个。如果都输入，以areaCode为准。
     * @param needMoreDay       是否需要返回7天数据中的后4天。1为返回，0为不返回。
     * @param needIndex         是否需要返回指数数据，比如穿衣指数、紫外线指数等。1为返回，0为不返回。
     * @param need3HourForecast 是否需要每小时数据的累积数组。由于本系统是半小时刷一次实时状态，因此实时数组最大长度为48。每天0点长度初始化为0. 1为需要 0为不
     * @param needAlarm         是否需要天气预警。1为需要，0为不需要。
     * @param needHourData      是否需要每小时数据的累积数组。由于本系统是半小时刷一次实时状态，因此实时数组最大长度为48。每天0点长度初始化为0.
     * @return ApiResponse
     */
    public ApiResponse forecastByAreaSyncMode(String areaId, String area, String areaCode, String needMoreDay,
                                              String needIndex, String need3HourForecast, String needAlarm, String needHourData) {
        ApiRequest request = requestAreaBuild(areaId, area, areaCode, needMoreDay, needIndex, need3HourForecast, needAlarm, needHourData);

        return sendSyncRequest(request);
    }

    /**
     * 区号邮编异步查询天气预报
     *
     * @param postCode          邮编，比如上海200000
     * @param phoneCode         电话区号，比如上海021。 注意邮编和区号必须二选一输入。都输入时，以邮编为准。
     * @param needMoreDay       是否需要返回7天数据中的后4天。1为返回，0为不返回。
     * @param needIndex         是否需要返回指数数据，比如穿衣指数、紫外线指数等。1为返回，0为不返回。
     * @param needHourData      是否需要每小时数据的累积数组。由于本系统是半小时刷一次实时状态，因此实时数组最大长度为48。每天0点长度初始化为0.
     * @param need3HourForecast 是否需要每小时数据的累积数组。由于本系统是半小时刷一次实时状态，因此实时数组最大长度为48。每天0点长度初始化为0.
     * @param needAlarm         是否需要天气预警。1为需要，0为不需要。
     * @param callback          回调函数
     */
    public void forecastByPostCode(String postCode, String phoneCode, String needMoreDay, String needIndex,
                                   String needHourData, String need3HourForecast, String needAlarm, ApiCallback callback) {
        ApiRequest request = requestPostCodeBuild(postCode, phoneCode, needMoreDay, needIndex, needHourData, need3HourForecast, needAlarm);

        sendAsyncRequest(request, callback);
    }

    /**
     * 区号邮编查询天气预报
     *
     * @param postCode          邮编，比如上海200000
     * @param phoneCode         电话区号，比如上海021。 注意邮编和区号必须二选一输入。都输入时，以邮编为准。
     * @param needMoreDay       是否需要返回7天数据中的后4天。1为返回，0为不返回。
     * @param needIndex         是否需要返回指数数据，比如穿衣指数、紫外线指数等。1为返回，0为不返回。
     * @param needHourData      是否需要每小时数据的累积数组。由于本系统是半小时刷一次实时状态，因此实时数组最大长度为48。每天0点长度初始化为0.
     * @param need3HourForecast 是否需要每小时数据的累积数组。由于本系统是半小时刷一次实时状态，因此实时数组最大长度为48。每天0点长度初始化为0.
     * @param needAlarm         是否需要天气预警。1为需要，0为不需要。
     * @return ApiResponse
     */
    public ApiResponse forecastByPostCodeSyncMode(String postCode, String phoneCode, String needMoreDay, String needIndex,
                                                  String needHourData, String need3HourForecast, String needAlarm) {
        ApiRequest request = requestPostCodeBuild(postCode, phoneCode, needMoreDay, needIndex, needHourData, need3HourForecast, needAlarm);

        return sendSyncRequest(request);
    }

    /**
     * 历史天气异步查询
     *
     * @param area     地区名称。必须
     * @param callback 回调函数
     */
    public void forecastByAreaName(String area, ApiCallback callback) {
        ApiRequest request = requestAreaNameBuild(area);

        sendAsyncRequest(request, callback);
    }

    /**
     * 历史天气查询
     *
     * @param area 地区名称。必须
     * @return ApiResponse
     */
    public ApiResponse forecastByAreaNameSyncMode(String area) {
        ApiRequest request = requestAreaNameBuild(area);

        return sendSyncRequest(request);
    }

    /**
     * 历史天气异步查询
     *
     * @param areaId    地区id 必须
     * @param areaCode  地区code
     * @param area      地区名称。code和名称必须输入其中1个。如果都输入，以id为准
     * @param month     查询的月份，格式yyyyMM。最早的数据是2015年1月。
     * @param startDate 查询的开始日期，格式yyyyMMdd。最早的数据是2011年1月1日。
     * @param endDate   查询的结束日期，格式yyyyMMdd。最早的数据是2011年1月1日。
     * @param callback  回调函数
     */
    public void history(String areaId, String areaCode, String area, String month,
                        String startDate, String endDate, ApiCallback callback) {
        ApiRequest request = requestHistoryBuild(areaId, areaCode, area, month, startDate, endDate);

        sendAsyncRequest(request, callback);
    }

    /**
     * 历史天气查询
     *
     * @param areaId    地区id 必须
     * @param areaCode  地区code
     * @param area      地区名称。code和名称必须输入其中1个。如果都输入，以id为准
     * @param month     查询的月份，格式yyyyMM。最早的数据是2015年1月。
     * @param startDate 查询的开始日期，格式yyyyMMdd。最早的数据是2011年1月1日。
     * @param endDate   查询的结束日期，格式yyyyMMdd。最早的数据是2011年1月1日。
     * @return ApiResponse
     */
    public ApiResponse historySyncMode(String areaId, String areaCode, String area,
                                       String month, String startDate, String endDate) {
        ApiRequest request = requestHistoryBuild(areaId, areaCode, area, month, startDate, endDate);

        return sendSyncRequest(request);
    }

    /**
     * 通过景点异步查询天气预报
     *
     * @param area              景点名称 必须
     * @param needMoreDay       是否需要返回7天数据中的后4天，1为返回，0为不返回
     * @param needIndex         是否需要返回指数数据，比如穿衣指数、紫外线指数等。1为返回，0为不返回。
     * @param needHourData      是否需要每小时数据的累积数组。由于本系统是半小时刷一次实时状态，因此实时数组最大长度为48。每天0点长度初始化为0. 1为需要 0为不
     * @param need3HourForecast 是否需要当天每3/6小时一次的天气预报列表。1为需要，0为不需要。
     * @param needAlarm         是否需要天气预警。1为需要，0为不需要。
     * @param callback          回调函数
     */
    public void scenicSpot(String area, String needMoreDay, String needIndex, String needHourData,
                           String need3HourForecast, String needAlarm, ApiCallback callback) {
        ApiRequest request = requestScenicSpotBuild(area, needMoreDay, needIndex, needHourData, need3HourForecast, needAlarm);

        sendAsyncRequest(request, callback);
    }

    /**
     * 通过景点查询天气预报
     *
     * @param area              景点名称 必须
     * @param needMoreDay       是否需要返回7天数据中的后4天，1为返回，0为不返回
     * @param needIndex         是否需要返回指数数据，比如穿衣指数、紫外线指数等。1为返回，0为不返回。
     * @param needHourData      是否需要每小时数据的累积数组。由于本系统是半小时刷一次实时状态，因此实时数组最大长度为48。每天0点长度初始化为0. 1为需要 0为不
     * @param need3HourForecast 是否需要当天每3/6小时一次的天气预报列表。1为需要，0为不需要。
     * @param needAlarm         是否需要天气预警。1为需要，0为不需要。
     * @return ApiResponse
     */
    public ApiResponse scenicSpotSyncMode(String area, String needMoreDay, String needIndex,
                                          String needHourData, String need3HourForecast, String needAlarm) {
        ApiRequest request = requestScenicSpotBuild(area, needMoreDay, needIndex, needHourData, need3HourForecast, needAlarm);

        return sendSyncRequest(request);
    }

    /**
     * 通过GPS异步查询天气预报
     *
     * @param from              输入的坐标类型：
     *                          <p>1：GPS设备获取的角度坐标</p>
     *                          <p>2：GPS获取的米制坐标、sogou地图所用坐标</p>
     *                          <p>3：google地图、soso地图、aliyun地图、mapabc地图和amap地图所用坐标</p>
     *                          <p>4：3中列表地图坐标对应的米制坐标</p>
     *                          <p>5：百度地图采用的经纬度坐标</p>
     *                          <p>6：百度地图采用的米制坐标</p>
     *                          <p>7：mapbar地图坐标</p>
     *                          <p>8：51地图坐标</p>
     * @param lng               经度值 必须
     * @param lat               纬度值 必须
     * @param needMoreDay       是否需要返回7天数据中的后4天。1为返回，0为不返回
     * @param needIndex         是否需要返回指数数据，比如穿衣指数、紫外线指数等。1为返回，0为不返回
     * @param needHourData      是否需要每小时数据的累积数组。由于本系统是半小时刷一次实时状态，因此实时数组最大长度为48。每天0点长度初始化为0. 1为需要 0为不
     * @param need3HourForecast 是否需要当天每3/6小时一次的天气预报列表。1为需要，0为不需要
     * @param needAlarm         是否需要天气预警。1为需要，0为不需要
     * @param callback          回调函数
     */
    public void forecastByGPS(String from, String lng, String lat, String needMoreDay, String needIndex,
                              String needHourData, String need3HourForecast, String needAlarm, ApiCallback callback) {
        ApiRequest request = requestGPSBuild(from, lng, lat, needMoreDay, needIndex, needHourData, need3HourForecast, needAlarm);

        sendAsyncRequest(request, callback);
    }

    /**
     * 通过GPS查询天气预报
     *
     * @param from              输入的坐标类型：
     *                          <p>1：GPS设备获取的角度坐标</p>
     *                          <p>2：GPS获取的米制坐标、sogou地图所用坐标</p>
     *                          <p>3：google地图、soso地图、aliyun地图、mapabc地图和amap地图所用坐标</p>
     *                          <p>4：3中列表地图坐标对应的米制坐标</p>
     *                          <p>5：百度地图采用的经纬度坐标</p>
     *                          <p>6：百度地图采用的米制坐标</p>
     *                          <p>7：mapbar地图坐标</p>
     *                          <p>8：51地图坐标</p>
     * @param lng               经度值 必须
     * @param lat               纬度值 必须
     * @param needMoreDay       是否需要返回7天数据中的后4天。1为返回，0为不返回
     * @param needIndex         是否需要返回指数数据，比如穿衣指数、紫外线指数等。1为返回，0为不返回
     * @param needHourData      是否需要每小时数据的累积数组。由于本系统是半小时刷一次实时状态，因此实时数组最大长度为48。每天0点长度初始化为0. 1为需要 0为不
     * @param need3HourForecast 是否需要当天每3/6小时一次的天气预报列表。1为需要，0为不需要
     * @param needAlarm         是否需要天气预警。1为需要，0为不需要
     * @return ApiResponse
     */
    public ApiResponse forecastByGPSSyncMode(String from, String lng, String lat, String needMoreDay, String needIndex,
                                             String needHourData, String need3HourForecast, String needAlarm) {
        ApiRequest request = requestGPSBuild(from, lng, lat, needMoreDay, needIndex, needHourData, need3HourForecast, needAlarm);

        return sendSyncRequest(request);
    }
}
